﻿#region File Header
/***********************************************************************
 * Copyright © 2013 Beals Software
 * All Rights Reserved
************************************************************************
Author: Donald Beals
Date: February 4th, 2013
Description: TODO: Write a description of this file here.
****************************** Change Log ******************************
02.04.13 - Created initial file. (dbeals)
***********************************************************************/
#endregion

#region Using Statements
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using GameJolt;
#endregion

namespace GameJoltServices
{
	/// <summary>
	/// 
	/// </summary>
	public sealed class LoggedInUser : User
	{
		#region Variables
		private ServicesManager manager = null;
		private float autoPingDelay = 20000.0f;
		private System.Timers.Timer pingTimer = null;
		#endregion

		#region Properties
		public static LoggedInUser Guest
		{
			get
			{
				return new LoggedInUser(null, new GameJolt.User
					{
						Username = "Guest",
					}, string.Empty, UserIndex.Any)
				{
					IsGuest = true,
				};
			}
		}

		public string UserToken
		{
			get;
			private set;
		}

		public UserIndex UserIndex
		{
			get;
			private set;
		}

		public GameJolt.Session Session
		{
			get;
			private set;
		}

		public SessionStatus SessionStatus
		{
			get
			{
				return Session.Status;
			}
			set
			{
				Session.Status = value;
			}
		}

		public float AutoPingDelay
		{
			get
			{
				return autoPingDelay;
			}
			set
			{
				if(IsGuest)
					return; // Cannot ping a guest.

				autoPingDelay = value;
				pingTimer.Interval = value;
				if(autoPingDelay == 0.0f)
					pingTimer.Stop();
				else
					pingTimer.Start();
			}
		}

		public bool IsGuest
		{
			get;
			private set;
		}
		#endregion

		#region Constructors
		internal LoggedInUser(ServicesManager manager, GameJolt.User rawUser, string userToken, UserIndex userIndex = UserIndex.Any)
			: base(rawUser)
		{
			this.manager = manager;
			this.UserToken = userToken;
			this.UserIndex = userIndex;

			if(manager != null)
			{
				this.Session = new GameJolt.Session(rawUser.Username, userToken);

				pingTimer = new System.Timers.Timer();
				pingTimer.Interval = this.autoPingDelay;
				pingTimer.Elapsed += (sender, args) =>
				{
					if(this.Session.IsValid)
						this.Session.BeginPing(manager.GameID, manager.PrivateKey);
				};
			}
		}
		#endregion

		#region Methods
		public IAsyncResult BeginGetScores(string tableID, AsyncCallback callback = null, object asyncState = null)
		{
			if(IsGuest)
				return null;

			return GameJolt.Score.BeginGetScores(manager.GameID, manager.PrivateKey, Username, UserToken, 0, tableID, callback, asyncState);
		}

		public GameJolt.Score[] EndGetScores(IAsyncResult result)
		{
			if(IsGuest)
				return null;

			return GameJolt.Score.EndGetScores(result) ?? new GameJolt.Score[0];
		}

		public GameJolt.Score[] GetScores(string tableID)
		{
			if(IsGuest)
				return null;

			return GameJolt.Score.GetScores(manager.GameID, manager.PrivateKey, Username, UserToken, 0, tableID) ?? new GameJolt.Score[0];
		}

		public IAsyncResult GetScores(string tableID, Action<GameJolt.Score[]> callback)
		{
			if(IsGuest)
				return null;

			return GameJolt.Score.GetScores(manager.GameID, manager.PrivateKey, Username, UserToken, 0, tableID, callback);
		}

		public IAsyncResult BeginGetTrophy(string trophyID, AsyncCallback callback = null, object asyncState = null)
		{
			if(IsGuest)
				return null;

			return GameJolt.Trophy.BeginGetByID(manager.GameID, manager.PrivateKey, this.Username, this.UserToken, trophyID, callback, asyncState);
		}

		public Trophy EndGetTrophy(IAsyncResult result)
		{
			if(IsGuest)
				return null;

			return GameJolt.Trophy.EndGetByID(result);
		}

		public Trophy GetTrophy(string trophyID)
		{
			if(IsGuest)
				return null;

			return GameJolt.Trophy.GetByID(manager.GameID, manager.PrivateKey, this.Username, this.UserToken, trophyID);
		}

		public IAsyncResult BeginGetTrophies(GameJolt.TrophyFilter filter, AsyncCallback callback = null, object asyncState = null)
		{
			if(IsGuest)
				return null;

			return GameJolt.Trophy.BeginGetAll(manager.GameID, manager.PrivateKey, this.Username, this.UserToken, filter, callback, asyncState);
		}

		public GameJolt.Trophy[] EndGetTrophies(IAsyncResult result)
		{
			if(IsGuest)
				return null;

			return GameJolt.Trophy.EndGetAll(result);
		}

		public GameJolt.Trophy[] GetTrophies(GameJolt.TrophyFilter filter)
		{
			if(IsGuest)
				return null;

			return GameJolt.Trophy.GetAll(manager.GameID, manager.PrivateKey, this.Username, this.UserToken, filter);
		}

		public IAsyncResult GetTrophies(GameJolt.TrophyFilter filter, Action<GameJolt.Trophy[]> callback)
		{
			if(IsGuest)
				return null;

			return GameJolt.Trophy.GetAll(manager.GameID, manager.PrivateKey, this.Username, this.UserToken, filter, callback);
		}

		public IAsyncResult BeginUnlockTrophy(string trophyID, AsyncCallback callback = null, object asyncState = null)
		{
			if(IsGuest)
				return null;

			return GameJolt.Trophy.BeginGetByID(manager.GameID, manager.PrivateKey, this.Username, this.UserToken, trophyID, (result) =>
			{
				var info = GameJolt.Trophy.EndGetByID(result);
				if(info.Achieved == "false")
					GameJolt.Trophy.BeginAddTrophy(manager.GameID, manager.PrivateKey, this.Username, this.UserToken, trophyID, callback, asyncState);
			}, null);
		}

		public AddTrophyResult EndUnlockTrophy(IAsyncResult result)
		{
			if(IsGuest)
				return AddTrophyResult.IsGuest;

			var addResult = GameJolt.Trophy.EndAddTrophy(result);
			if(GameJolt.RequestHelper.WasSuccessful(addResult))
				return AddTrophyResult.Success;
			return AddTrophyResult.AlreadyAchieved;
		}

		public AddTrophyResult UnlockTrophy(string trophyID)
		{
			if(IsGuest)
				return AddTrophyResult.IsGuest;

			var result = GameJolt.Trophy.GetByID(manager.GameID, manager.PrivateKey, this.Username, this.UserToken, trophyID);
			if(result.Achieved == "false")
			{
				var addResult = GameJolt.Trophy.AddTrophy(manager.GameID, manager.PrivateKey, this.Username, this.UserToken, trophyID);
				if(GameJolt.RequestHelper.WasSuccessful(addResult))
					return AddTrophyResult.Success;
				return AddTrophyResult.Failure;
			}
			return AddTrophyResult.AlreadyAchieved;
		}
		#endregion
	}
}
